package com.xm.cas;

import java.util.concurrent.atomic.AtomicMarkableReference;

/**
 * 状态标记：
 *   T1 先将引用从 0 设置为 1 并打上标记，然后再将其恢复为 0 并清除标记。
 *   T2 在等待期间错过了中间的修改过程，在最终判断时发现引用仍然是 0，但由于标记已经被清除，因此无法成功地将 0 更改为 1。
 */
public class AtomicMarkableReference02 {
    public static void main(String[] args) throws InterruptedException {
        Integer initialRef = 0;
        boolean initialMark = false;
        AtomicMarkableReference<Integer> markableReference = new AtomicMarkableReference<>(initialRef, initialMark);

        Thread t1 = new Thread(() -> {
            try {
                Integer reference = markableReference.getReference();
                boolean marked = markableReference.isMarked();
                System.out.println("T1 got ref: " + reference + ", ismarked: " + marked);

                boolean updatedTo1 = markableReference.compareAndSet(reference, 1, marked, true);
                System.out.println("T1 set to 1? " + updatedTo1);

                // 等待一段时间让主线程也获取到初始状态
                Thread.sleep(100);

                boolean restoredToInitial = markableReference.compareAndSet(1, 0, true, true);
                System.out.println("T1 restore to 0? " + restoredToInitial);

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                Integer reference = markableReference.getReference();
                boolean marked = markableReference.isMarked();

                // 等待一段时间以便 T1 完成分两次修改
                Thread.sleep(200);

                // 尝试将 0 改为 1
                boolean success = markableReference.compareAndSet(reference, 1, marked, !marked);
                System.out.println("T2 set from 0 to 1 successful? " + success +
                        ". Current Ref: " + markableReference.getReference() +
                        ", Is Marked: " + markableReference.isMarked());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}
